<!DOCTYPE html>
<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
 <meta charset="UTF-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 <title>一起看 - 淡白影视</title>
 <meta name="Keywords" content="淡白影视,一起观看,同步观看" />
 <meta name="Description" content="一起看,一个在线和朋友一起观看影视的地方." />
 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
 <link rel="icon" href="https://cdn.p00q.cn/favicon.ico" />
 <link rel="stylesheet" href="https://cdn.p00q.cn/ys/css/bootstrap.min.css" />
 <link rel="stylesheet" rev="stylesheet" type="text/css" media="all" href="https://cdn.p00q.cn/ys/css/bootadd.css" />
 <link rel="stylesheet" rev="stylesheet" type="text/css" media="all" href="https://cdn.p00q.cn/ys/css/css2.css" />
 <link rel="stylesheet" href="https://cdn.p00q.cn/ys/css/notiflix-1.3.0.min.css" />
 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.css" />
</head>
<body>
<div id="main">
 <!--首页-->
 <div id="shouye">
  <div id="rooms">
   <div>
    当前在线人数:
    <span id="online">1</span>
   </div>
   <div class="row">
    <div class="col-md-4">
     房间名
    </div>
    <div class="col-md-4">
     房主
    </div>
    <div class="col-md-2">
     房间人数
    </div>
    <div class="col-md-2">
     加入
    </div>
   </div>
  </div>
  <button type="button" class="btn btn-primary" id="shouyeBt">刷新</button>
  <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#newRoom">创建房间</button>
  <div class="modal fade" id="newRoom" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
   <div class="modal-dialog" role="document">
    <div class="modal-content">
     <div class="modal-header">
      <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      <h4 class="modal-title" id="exampleModalLabel">创建房间</h4>
     </div>
     <div class="modal-body">
      <form>
       <div class="form-group">
        <label for="newRoom-name" class="control-label">房间名字</label>
        <input type="text" class="form-control" id="newRoom-name" />
       </div>
       <div class="form-group">
        <label for="newRoom-pass" class="control-label">房间密码(不设置留空即可)</label>
        <input type="password" class="form-control" id="newRoom-pass" />
       </div>
      </form>
     </div>
     <div class="modal-footer">
      <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
      <button type="button" class="btn btn-primary" id="newRoomSub" data-dismiss="modal">创建</button>
     </div>
    </div>
   </div>
  </div>
 </div>
 <!--房间内-->
 <div id="fangjian">
  <h3 id="fangjianInfo"></h3>
  <div class="col-md-8" id="dplayer">
  </div>
  <div class="col-md-4">
   <ul id="myTab" class="nav nav-tabs">
    <li class="active"> <a href="#chat" data-toggle="tab">聊天</a> </li>
    <li><a href="#users" data-toggle="tab">在线用户<span id="roomOnline"></span></a></li>
    <li id="selectYsTab"><a href="#selectYs" data-toggle="tab">选择影视</a></li>
    <li id="yuyinTab"><a href="#yuyin" data-toggle="tab">语音设置</a></li>
    <li><button class="btn btn-default exitRoom">退出房间</button></li>
   </ul>
   <div id="myTabContent" class="tab-content">
    <div class="tab-pane fade in active" id="chat">
     <div id="statements">
     </div>
     <div>
      <div class="input-group">
       <input type="text" id="chatIupt" class="form-control" placeholder="请输入发送内容..." />
       <span class="input-group-btn"> <button class="btn btn-default sendChat" type="button">发送</button> </span>
      </div>
     </div>
    </div>
    <div class="tab-pane fade" id="users">
    </div>
    <div class="tab-pane fade" id="selectYs">
     <div id="ysSou">
      <div class="input-group">
       <input type="text" class="form-control" id="ysSouInput" placeholder="请输入影视关键字,片名、导演、演员用于搜索" />
       <span class="input-group-btn"> <button class="btn btn-default" id="ysSouBt" type="button">搜索</button> </span>
      </div>
      <!-- /input-group -->
     </div>
     <div id="yss">
     </div>
     <div id="jis">
     </div>
    </div>
    <div class="tab-pane fade" id="yuyin">
     <button class="btn btn-raised btn-primary waves-effect waves-light" id="join">加入</button>
   <button class="btn btn-raised btn-primary waves-effect waves-light" id="leave">断开</button>
        <div class="video-grid" id="video">
         <div class="video-view">
          <div id="local_stream" class="video-placeholder"></div>
          <div id="local_video_info" class="video-profile hide"></div>
          <div id="video_autoplay_local" class="autoplay-fallback hide"></div>
         </div>

    </div>
   </div>
  </div>
 </div>
</div>
<script src="https://cdn.p00q.cn/ys/js/jquery.min.js"></script>
<script src="https://cdn.p00q.cn/ys/js/bootstrap.min.js"></script>
<script src="https://cdn.p00q.cn/ys/js/notiflix-1.3.0.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/artDialog/7.0.0/dialog.js" type="text/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/cdnbye@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/p2p-dplayer@latest"></script>
<script src="https://cdn.p00q.cn/ys/js/AgoraRTCSDK-3.0.1.js"></script>
<script src="https://cdn.p00q.cn/ys/js/reconnecting-websocket.min.js"></script>
<script th:inline="javascript">
 if(window.location.protocol.split(':')[0]!="https"){
  window.location="https://dbys.vip/yiqikan";
 }
 /*<![CDATA[*/
 var username = /*[[${session.user.username}]]*/ null;
 /*]]>*/
 fangzhu = null;
 ysurl = "";
 wsurl="wss://dbys.vip/wss/cinema/socket/"+username;
 //播放器
 const dp = new DPlayer({
  autoplay: true,
  container: document.getElementById('dplayer'),
  logo: 'https://cdn.p00q.cn/ys/img/logo.png',
  theme: '#FFFFF0',
  live: false,
  danmaku: true,
  video: {
   pic: 'https://cdn.p00q.cn/ys/img/tip.png',
   url: "",
   type: 'hls'
  },
  contextmenu: [
   {
    text: '淡白博客',
    link: 'https://p00q.cn',
   }],
  apiBackend: {
   read: function (options) {
    options.success();
   },
   send: function (options) {
    console.log(options)
    if (options.data.color != "#b7daff") {
     ws.send(JSON.stringify({ type: "sendChat", msg: options.data.text }));
     $(".dplayer-comment-input").val("");
    }
   }
  }
 });
 //切换播放url
 function dpurl(url) {
  if(url!=null){
   ysurl = url;
   dp.switchVideo({
    url: url,
    pic: 'https://cdn.p00q.cn/ys/img/tip.png'
   });
   dp.notice("正在加载请稍后!");
   dp.play();
  }
 }
 //初始化
 $(function () {
  $("#fangjian").hide();
  $("#jis").hide();
  Notiflix.Notify.Init();
  Notiflix.Report.Init();
  Notiflix.Confirm.Init();
  Notiflix.Loading.Init({
   clickToClose: true
  });
 });

 var ws = new ReconnectingWebSocket(wsurl);
 //回调、事件函数区
 ws.onopen = function (evt) {
  console.log('连接到服务器');
 };

 ws.onmessage = function (evt) {
  var json = JSON.parse(evt.data);
  console.log(json);
  switch (json.type) {
   case "info":
    info(json);
    break;
   case "join":
    join(json);
    break;
   case "roomInfo":
    roomInfo(json);
    break;
   case "sendChat": sendChat(json); break;
   case "sendUrl": sendUrl(json.url); break;
   case "sendTime": sendTime(json.time); break;
  }
 };
 ws.onclose = function () {
  console.log('断开了连接');
  if(fangzhu!=null){
   console.log(123)
  }
 };
 //加入房间
 function joinbt(e) {
  id = $(e).parent().parent().parent().attr("roomId");
  //是否需要密码
  if ($(e).parent().parent().parent().attr("pass") == "true") {
   var d = dialog({
    title: '请输入房间密码',
    content: '<input id="roomPass"/>',
    ok: function () {
     ws.send(toJsonStr({ type: "join", roomId: id, pass: $("#roomPass").val() }));
    }
   });
   d.showModal();
  } else {
   ws.send(toJsonStr({ type: "join", roomId: id, pass: "" }));
  }

 }
 //创建房间
 $('#newRoomSub').click(function () {
  var type = {
   type: "newRoom",
   name: $('#newRoom-name').val()
   , pass: $('#newRoom-pass').val()
  }
  if (type.name == "") {
   Notiflix.Notify.Warning('房间名不能为空!');
   return;
  }
  ws.send(toJsonStr(type));
 })
 //刷新
 $("#shouyeBt").click(getinfo)
 //影视搜索
 $("#ysSouBt").click(function () {
  gjc = $("#ysSouInput").val();
  $.ajax({
   url: '../api/v1/ys/search/' + gjc,
   type: 'get',
   dataType: 'json',
   success: function (data) {

    addys(data.data);
   },
   error: function (err) {
    console.log(err)
   }
  })
 })
 //影视选择
 function ysClick(id) {
  $('#yss').hide();
  $('#jis').show();
  $.ajax({
   url: '../api/v1/ys/' + id,
   type: 'get',
   dataType: 'json',
   success: function (data) {
    addji(data.data);
   },
   error: function (err) {
    console.log(err)
   }
  })
 }
 //集选择
 function jiClick(url) {
  ws.send(toJsonStr({ type: "sendUrl", url: url }));
  dpurl(url);
 }
 //dom操作方法区
 function info(data) {
  $("#online").html(data.online);
  data.rooms.forEach(room => {
   var roomd = '<div class="room" roomId="' + room.id + '" pass="' + room.needPass + '"><div class="row"><div class="col-md-4">' + room.name + '</div><div class="col-md-4">' + room.author + '</div><div class="col-md-2">' + room.online + '</div><div class="col-md-2"><button type="button" onclick="joinbt(this)" class="btn btn-success">加入</button></div></div></div>'
   $('#rooms').append(roomd);
 });
 }
 //发送消息
 $(".sendChat").click(function () {
  msg = $("#chatIupt").val();
  if (msg == "") {
   return
  }
  type = {
   type: "sendChat", msg: msg
  }
  ws.send(toJsonStr(type));
  $("#chatIupt").val("");
 })

 $("#chatIupt").keydown(function(e) {
  if (e.keyCode == 13) {
   msg = $("#chatIupt").val();
   if (msg == "") {
    return
   }
   type = {
    type: "sendChat", msg: msg
   }
   ws.send(toJsonStr(type));
   $("#chatIupt").val("");
  }
 });
 function getinfo() {
  $('.room').remove();
  ws.send(toJsonStr({ type: "info" }));
 }
 //加入房间
 function join(data) {
  if (data.ok) {
   Notiflix.Notify.Success('加入成功');
   $("#shouye").hide();
   $("#fangjian").show();
   ws.send(toJsonStr({ type: "roomInfo" }));
   options.uid=data.uid;
   options.channel=data.channel;
   options.token=data.token;
  } else {
   Notiflix.Notify.Failure('加入失败');
  }
 }
 //房间信息
 function roomInfo(data) {
  if (ysurl != data.url) {
   dpurl(data.url);
  }
  fangzhu = data.author;
  if (data.author == username) {
   $('#selectYsTab').show();
  } else {
   $('#selectYsTab').hide();
  }
  $("#fangjianInfo").html("房间名:" + data.name + " ---房主:" + data.author);
  $("#roomOnline").html('(' + data.online + ')');
  $(".user").remove();
  data.users.forEach(user => {
   if(username==data.author&user.username!=username){
    u='<div class="user" uid="' + user.id + '">' + user.username +'<button class="btn btn-success" type="button" onclick="transfer('+user.id+')">给他房主</button>'+'</div>';
  }else{
    if(user.username==data.author){
     u = '<div class="user" uid="' + user.id + '">' + user.username + '👑</div>';
    }else {
     u = '<div class="user" uid="' + user.id + '">' + user.username + '</div>';
    }

  }
  $('#users').append(u);
 })
 }
 //收到消息
 function sendChat(data) {
  s = '<div class="statement"><div class="statement-time">' + getFormatDate() + '</div><span class="statement-username">' + data.username + ':</span><span class="statement-text">' + data.msg + '</span></div>'
  $('#statements').append(s);
  dp.danmaku.send(
          {
           text: data.msg,
           color: '#b7daff',
           type: 'right', // should be `top` `bottom` or `right`
          }
  );
 }
 function transfer(id){
  ws.send(toJsonStr({type:"transfer",id:id}));
 }
 //退出房间
 $('.exitRoom').click(function(){
  fangzhu=null;
  ysurl=null;
  ws.send(toJsonStr({type:"exitRoom"}))
  $("#shouye").show();
  $("#fangjian").hide();
  publish(rtc);
  dp.pause();
 })
 //url
 function sendUrl(url) {
  if (username != fangzhu) {
   dpurl(url);
  }
 }
 function sendTime(time) {
  if (Math.abs(dp.video.currentTime - time) > 5) {
   dp.seek(time);
  }
 }
 //影视搜索结果
 function addys(data) {
  $("#yss").show();
  $("#jis").hide();
  $(".movie-item").remove();
  data.forEach(ysdata => {
   ys = '<div class="movie-item" onclick="ysClick(' + ysdata.id + ')"><span style="position:relative;display:block;" target="_blank" title="' + ysdata.pm + '"><img class="indexhot" src="' + ysdata.tp + '" alt="淡白影视-' + ysdata.pm + '"><button class="hdtag">' + ysdata.zt + '</button></span><div class="meta"><span style="width:100%;overflow:hidden;height:20px;"><span target="_blank" class="movie-name" href="ys?id=51377">' + ysdata.pm + '</span></div><em>添加时间：<strong><span style="color:#FF0000;">' + ysdata.gxtime + '</span></strong></em></div>';
  $("#yss").append(ys);
 })
 }
 //影视选择添加集
 function addji(data) {
  $('.ji').remove();
  var jsonObj = $.parseJSON(data.gkdz);
  jsonObj.forEach(j => {
   jdom = '<button class="ji btn btn-success" type="button" onclick="jiClick(\'' + j.url + '\')">' + j.name + '</button>';
  $('#jis').append(jdom);
 })
 }
 //工具方法
 function toJsonStr(obj) {
  return JSON.stringify(obj, null, 4);
 }

 //时间格式
 function getFormatDate() {
  var date = new Date();
  var month = date.getMonth() + 1;
  var strDate = date.getDate();
  if (month >= 1 && month <= 9) {
   month = "0" + month;
  }
  if (strDate >= 0 && strDate <= 9) {
   strDate = "0" + strDate;
  }
  var currentDate = date.getFullYear() + "-" + month + "-" + strDate
          + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
  return currentDate;
 }


 //定时器

 //首页信息刷新
 var shouYeTimerId = setInterval(function () {
  if (!$("#shouye").is(":hidden")) {
   getinfo();
  }
 }, 10000);
 //观看时间发送
 var guanKanTimerId = setInterval(function () {
  if ($("#shouye").is(":hidden")) {
   if (username == fangzhu) {
    ws.send(toJsonStr({ type: "sendTime", time: dp.video.currentTime }));
   }
  }
 }, 1000);
 //房间信息刷新
 var roomTimerId = setInterval(function () {
  if ($("#shouye").is(":hidden")) {
   ws.send(toJsonStr({ type: "roomInfo" }));

  }
 }, 5000);


 function validator(formData, fields) {
  var keys = Object.keys(formData);
  for (let key of keys) {
   if (fields.indexOf(key) != -1) {
    if (!formData[key]) {

     return false;
    }
   }
  }
  return true;
 }


 function addView (id, show) {
  if (!$("#" + id)[0]) {
   $("<div/>", {
    id: "remote_video_panel_" + id,
    class: "video-view",
   }).appendTo("#video");

   $("<div/>", {
    id: "remote_video_" + id,
    class: "video-placeholder",
   }).appendTo("#remote_video_panel_" + id);

   $("<div/>", {
    id: "remote_video_info_" + id,
    class: "video-profile " + (show ? "" :  "hide"),
   }).appendTo("#remote_video_panel_" + id);

   $("<div/>", {
    id: "video_autoplay_"+ id,
    class: "autoplay-fallback hide",
   }).appendTo("#remote_video_panel_" + id);
  }
 }
 function removeView (id) {
  if ($("#remote_video_panel_" + id)[0]) {
   $("#remote_video_panel_"+id).remove();
  }
 }


 var rtc = {
  client: null,
  joined: false,
  published: false,
  localStream: null,
  remoteStreams: [],
  params: {}
 };
 var options={
  appID: "02e8df44f24e4da5b2e17ef1d8b755bd",
  channel: "",
  token: "",
  uid:"",
  mode: "live",
  video: "false",
  codec: "h264",
 };
 function handleEvents (rtc) {
  // Occurs when an error message is reported and requires error handling.
  rtc.client.on("error", (err) => {
   console.log(err)
  })
  // Occurs when the peer user leaves the channel; for example, the peer user calls Client.leave.
  rtc.client.on("peer-leave", function (evt) {
   var id = evt.uid;
   console.log("id", evt);
   if (id != rtc.params.uid) {
    removeView(id);
   }

   console.log('peer-leave', id);
  })
  // Occurs when the local stream is published.
  rtc.client.on("stream-published", function (evt) {

   console.log("stream-published");
  })
  // Occurs when the remote stream is added.
  rtc.client.on("stream-added", function (evt) {
   var remoteStream = evt.stream;
   var id = remoteStream.getId();

   if (id !== rtc.params.uid) {
    rtc.client.subscribe(remoteStream, function (err) {
     console.log("stream subscribe failed", err);
    })
   }
   console.log('stream-added remote-uid: ', id);
  });
  // Occurs when a user subscribes to a remote stream.
  rtc.client.on("stream-subscribed", function (evt) {
   var remoteStream = evt.stream;
   var id = remoteStream.getId();
   rtc.remoteStreams.push(remoteStream);
   addView(id);
   remoteStream.play("remote_video_" + id);

   console.log('stream-subscribed remote-uid: ', id);
  })
  // Occurs when the remote stream is removed; for example, a peer user calls Client.unpublish.
  rtc.client.on("stream-removed", function (evt) {
   var remoteStream = evt.stream;
   var id = remoteStream.getId();

   remoteStream.stop("remote_video_" + id);
   rtc.remoteStreams = rtc.remoteStreams.filter(function (stream) {
    return stream.getId() !== id
   })
   removeView(id);
   console.log('stream-removed remote-uid: ', id);
  })
  rtc.client.on("onTokenPrivilegeWillExpire", function(){
   // After requesting a new token
   // rtc.client.renewToken(token);

   console.log("onTokenPrivilegeWillExpire")
  });
  rtc.client.on("onTokenPrivilegeDidExpire", function(){
   // After requesting a new token
   // client.renewToken(token);

   console.log("onTokenPrivilegeDidExpire")
  })
 }

 /**
  * rtc: rtc object
  * option: {
  *  mode: string, 'live' | 'rtc'
  *  codec: string, 'h264' | 'vp8'
  *  appID: string
  *  channel: string, channel name
  *  uid: number
  *  token; string,
  * }
  **/
 function joinyuyin (rtc, option) {
  if (rtc.joined) {

   return;
  }


  rtc.client = AgoraRTC.createClient({mode: option.mode, codec: option.codec});

  rtc.params = option;

  // handle AgoraRTC client event
  handleEvents(rtc);

  // init client
  rtc.client.init(option.appID, function () {
   console.log("init success");



   rtc.client.join(option.token ? option.token : null, option.channel, option.uid ? +option.uid : null, function (uid) {

    console.log("join channel: " + option.channel + " success, uid: " + uid);
    rtc.joined = true;

    rtc.params.uid = uid;

    // create local stream
    var ifv=$('.videor:radio:checked').val()=="true"?true:false;
    rtc.localStream = AgoraRTC.createStream({
     streamID: rtc.params.uid,
     audio: true,
     video: ifv,
     screen: false,
     microphoneId: option.microphoneId,
     cameraId: option.cameraId
    })

    // init local stream
    rtc.localStream.init(function () {
     console.log("init local stream success");
     // play stream with html element id "local_stream"
     rtc.localStream.play("local_stream")

     // publish local stream
     publish(rtc);
    }, function (err)  {

     console.error("init local stream failed ", err);
    })
   }, function(err) {

    console.error("client join failed", err)
   })
  }, (err) => {

   console.error(err);
 });
 }

 function publish (rtc) {
  if (!rtc.client) {

   return;
  }
  if (rtc.published) {

   return;
  }
  var oldState = rtc.published;

  // publish localStream
  rtc.client.publish(rtc.localStream, function (err) {
   rtc.published = oldState;
   console.log("publish failed");

   console.error(err);
  })

  rtc.published = true
 }
 function leave (rtc) {
  if (!rtc.client) {

   return;
  }
  if (!rtc.joined) {
   return;
  }
  /**
   * Leaves an AgoraRTC Channel
   * This method enables a user to leave a channel.
   **/
  rtc.client.leave(function () {
   // stop stream
   rtc.localStream.stop();
   // close stream
   rtc.localStream.close();
   while (rtc.remoteStreams.length > 0) {
    var stream = rtc.remoteStreams.shift();
    var id = stream.getId();
    stream.stop();
    removeView(id);
   }
   rtc.localStream = null;
   rtc.remoteStreams = [];
   rtc.client = null;
   console.log("client leaves channel success");
   rtc.published = false;
   rtc.joined = false;

  }, function (err) {
   console.log("channel leave failed");

   console.error(err);
  })
 }
 $(function () {

  $("#join").on("click", function (e) {
   console.log("join")
   e.preventDefault();
   joinyuyin(rtc, options);
  })

  $("#leave").on("click", function (e) {
   console.log("leave")
   e.preventDefault();
    leave(rtc);
 })
 })
</script>
<style>
 body {
  text-align: center;
 }

 #main {
  margin: 0px auto;
 }

 .room {
  margin: 4px;
  font-size: 2rem;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  background-color: azure;
 }

 #statements {
  height: 600px;
  text-align: left;
  border: 1px solid greenyellow;
  overflow: auto;
 }

 .statement {
  margin: 10px 20px;
 }

 .movie-item {
  width: 180px;
  display: inline-block;
 }

 #yss {
  overflow: auto;
  max-height: 600px;
 }

 /* 小屏幕（平板，大于等于 ） */
 @media (min-width: 480px) {
  #rooms {
   margin: 0px auto;
   width: 100%;
  }
 }

 /* 小屏幕（平板，大于等于 ） */
 @media (min-width: 768px) {
  #rooms {
   margin: 0px auto;
   width: 80%;
  }
 }

 /* 中等屏幕（桌面显示器，大于等于 ） */
 @media (min-width: 992px) {
  #rooms {
   margin: 0px auto;
   width: 30%;
  }
 }

 /* 大屏幕（大桌面显示器，大于等于 ） */
 @media (min-width: 1200px) {}
</style>
</body>
</html>